package com.ruoyi.common.utils.media;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.*;
import java.util.Hashtable;

/**
 * @author xumh
 * @title: QRCodeUtil
 * @projectName ruoyi
 * @description: TODO
 * @date 2024/12/1216:02
 */
public class QRCodeUtil {
    private static Logger logger = LoggerFactory.getLogger(QRCodeUtil.class);

    private QRCodeUtil() {
    }

    public static boolean encodeQRCodeImage(String content, String charset, String imagePath, Integer width, Integer height, String logoPath) {
        width = width != null && width != 0 ? width : 200;
        height = height != null && height != 0 ? height : 200;
        Hashtable<EncodeHintType, Object> hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.MARGIN, 1);
        BufferedImage image = null;
        BitMatrix matrix = null;

        try {
            matrix = (new MultiFormatWriter()).encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            matrix = deleteWhite(matrix);
            image = MatrixToImageWriter.toBufferedImage(matrix);
        } catch (WriterException var13) {
            var13.printStackTrace();
            logger.error("WriterException err:" + var13.getMessage());
            return false;
        }

        BufferedImage outImage = new BufferedImage(image.getWidth(), image.getHeight(), 1);
        BufferedImage logoImage = null;
        if (logoPath != null && !logoPath.isEmpty()) {
            try {
                logoImage = ImageIO.read(new File(logoPath));
                overlapImage(outImage, image, logoImage);
            } catch (IOException var12) {
                var12.printStackTrace();
                logger.error("logo inputstream err:" + var12.getMessage());
            }
        }

        try {
            if (logoPath != null && !logoPath.isEmpty()) {
                ImageIO.write(outImage, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
            } else {
                ImageIO.write(image, imagePath.substring(imagePath.lastIndexOf(".") + 1), new File(imagePath));
            }

            return true;
        } catch (IOException var14) {
            var14.printStackTrace();
            logger.error("ImageIO.write err:" + var14.getMessage());
            return false;
        }
    }

    public static boolean encodeQRCodeImage(String content, String charset, OutputStream os, Integer width, Integer height, String logoPath) {
        width = width != null && width != 0 ? width : 200;
        height = height != null && height != 0 ? height : 200;
        Hashtable<EncodeHintType, Object> hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.MARGIN, 0);
        BufferedImage image = null;
        BitMatrix matrix = null;

        try {
            matrix = (new MultiFormatWriter()).encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            matrix = deleteWhite(matrix);
            image = MatrixToImageWriter.toBufferedImage(matrix);
        } catch (WriterException var13) {
            var13.printStackTrace();
            logger.error("WriterException err:" + var13.getMessage());
            return false;
        }

        BufferedImage outImage = new BufferedImage(image.getWidth(), image.getHeight(), 1);
        BufferedImage logoImage = null;
        if (logoPath != null && !logoPath.isEmpty()) {
            try {
                logoImage = ImageIO.read(new File(logoPath));
                overlapImage(outImage, image, logoImage);
            } catch (IOException var12) {
                var12.printStackTrace();
                logger.error("logo inputstream err:" + var12.getMessage());
            }
        }

        try {
            if (logoPath != null && !logoPath.isEmpty()) {
                ImageIO.write(outImage, "png", os);
            } else {
                ImageIO.write(image, "png", os);
            }

            return true;
        } catch (IOException var14) {
            var14.printStackTrace();
            logger.error("ImageIO.write err:" + var14.getMessage());
            return false;
        }
    }

    private static void overlapImage(BufferedImage outImage, BufferedImage inImage, BufferedImage logoImage) {
        int logoWidth = inImage.getWidth() / 5;
        int logoHeight = inImage.getHeight() / 5;
        int logoX = (inImage.getWidth() - logoWidth) / 2;
        int logoY = (inImage.getHeight() - logoHeight) / 2;
        Graphics2D graphics = outImage.createGraphics();
        graphics.drawImage(inImage, 0, 0, inImage.getWidth(), inImage.getHeight(), (ImageObserver)null);
        graphics.setBackground(Color.white);
        graphics.clearRect(logoX, logoY, logoWidth, logoHeight);
        graphics.drawImage(logoImage, logoX, logoY, logoWidth, logoHeight, (ImageObserver)null);
        BasicStroke stroke = new BasicStroke(3.0F, 1, 1);
        graphics.setStroke(stroke);
        RoundRectangle2D.Float round = new RoundRectangle2D.Float((float)logoX, (float)logoY, (float)logoWidth, (float)logoHeight, 10.0F, 10.0F);
        graphics.setColor(Color.white);
        graphics.draw(round);
        graphics.dispose();
    }

    private static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();

        for(int i = 0; i < resWidth; ++i) {
            for(int j = 0; j < resHeight; ++j) {
                if (matrix.get(i + rec[0], j + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }

        return resMatrix;
    }

    public static void main(String[] args) {
        try {
            for(int i=1;i<=10;i++){
                FileOutputStream fos = new FileOutputStream(new File("C://qrimage//test-"+i+".png"));
                encodeQRCodeImage("http://www.baidu.com", "utf-8", (OutputStream)fos, 0, 0, "");
            }
        } catch (FileNotFoundException var2) {
            var2.printStackTrace();
        }

    }
}
